"""
项目仓储
"""
from typing import List, Optional
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload

from app.models.project import Project, ProjectStatus, ScenarioType
from app.schemas.project import ProjectCreate, ProjectUpdate
from app.repositories.base import BaseRepository


class ProjectRepository(BaseRepository[Project, ProjectCreate, ProjectUpdate]):
    """项目仓储"""
    
    def __init__(self):
        super().__init__(Project)
    
    async def get_with_relations(self, db: AsyncSession, id: int) -> Optional[Project]:
        """获取项目及其关联数据"""
        stmt = select(Project).options(
            selectinload(Project.data_sources),
            selectinload(Project.training_jobs),
            selectinload(Project.models),
            selectinload(Project.owner)
        ).where(Project.id == id)
        result = await db.execute(stmt)
        return result.scalar_one_or_none()
    
    async def get_by_owner(
        self, 
        db: AsyncSession, 
        *, 
        owner_id: int, 
        skip: int = 0, 
        limit: int = 100
    ) -> List[Project]:
        """获取用户的项目列表"""
        return await self.get_multi(
            db,
            skip=skip,
            limit=limit,
            filters={"owner_id": owner_id, "status": ProjectStatus.ACTIVE}
        )
    
    async def get_by_scenario_type(
        self, 
        db: AsyncSession, 
        *, 
        scenario_type: ScenarioType, 
        skip: int = 0, 
        limit: int = 100
    ) -> List[Project]:
        """根据场景类型获取项目"""
        return await self.get_multi(
            db,
            skip=skip,
            limit=limit,
            filters={"scenario_type": scenario_type, "status": ProjectStatus.ACTIVE}
        )
    
    async def get_public_projects(
        self, 
        db: AsyncSession, 
        *, 
        skip: int = 0, 
        limit: int = 100
    ) -> List[Project]:
        """获取公开项目列表"""
        return await self.get_multi(
            db,
            skip=skip,
            limit=limit,
            filters={"is_public": True, "status": ProjectStatus.ACTIVE}
        )
    
    async def search_projects(
        self, 
        db: AsyncSession, 
        *, 
        keyword: str, 
        owner_id: Optional[int] = None,
        scenario_type: Optional[ScenarioType] = None,
        skip: int = 0, 
        limit: int = 100
    ) -> List[Project]:
        """搜索项目"""
        stmt = select(Project).where(
            (Project.name.like(f"%{keyword}%")) |
            (Project.description.like(f"%{keyword}%"))
        )
        
        if owner_id:
            stmt = stmt.where(Project.owner_id == owner_id)
        
        if scenario_type:
            stmt = stmt.where(Project.scenario_type == scenario_type)
        
        stmt = stmt.where(Project.status == ProjectStatus.ACTIVE)
        stmt = stmt.offset(skip).limit(limit)
        
        result = await db.execute(stmt)
        return result.scalars().all()
    
    async def get_project_stats(self, db: AsyncSession, project_id: int):
        """获取项目统计信息"""
        stmt = select(
            func.count(Project.id).label("total_projects"),
            func.sum(Project.training_jobs_count).label("total_training_jobs"),
            func.sum(Project.models_count).label("total_models"),
            func.sum(Project.data_sources_count).label("total_data_sources")
        ).where(Project.id == project_id)
        
        result = await db.execute(stmt)
        return result.first()
    
    async def update_counts(self, db: AsyncSession, project_id: int):
        """更新项目的统计计数"""
        # 这里需要导入相关模型来计算统计数据
        # 为了避免循环导入，可以在服务层实现这个逻辑
        pass
    
    async def get_projects_by_status(
        self, 
        db: AsyncSession, 
        *, 
        status: ProjectStatus,
        skip: int = 0, 
        limit: int = 100
    ) -> List[Project]:
        """根据状态获取项目"""
        return await self.get_multi(
            db,
            skip=skip,
            limit=limit,
            filters={"status": status}
        )
    
    async def archive_project(self, db: AsyncSession, project_id: int) -> Optional[Project]:
        """归档项目"""
        project = await self.get(db, project_id)
        if project:
            project.status = ProjectStatus.ARCHIVED
            db.add(project)
            await db.commit()
            await db.refresh(project)
        return project


# 创建仓储实例
project_repository = ProjectRepository()